package com.biz.primus.ms.product.interfaces.impl;


import com.biz.primus.base.constant.Constant;
import com.biz.primus.base.enums.PeriodsOfDeliveriesTime;
import com.biz.primus.base.enums.commodity.DeliverType;
import com.biz.primus.base.enums.vendor.VendorType;
import com.biz.primus.base.vo.*;
import com.biz.primus.base.vo.commodity.ProductBaseVo;
import com.biz.primus.base.vo.commodity.ProductFinalPriceVo;
import com.biz.primus.base.vo.commodity.ProductPriceVo;
import com.biz.primus.base.vo.commodity.ProductStockVo;
import com.biz.primus.base.vo.search.ProductIdxVo;
import com.biz.primus.commodity.vo.CommodityVo;
import com.biz.primus.commodity.vo.DepotCommodityVo;
import com.biz.primus.commodity.vo.frontend.ProductCustomModelVo;
import com.biz.primus.common.utils.CopyUtils;
import com.biz.primus.common.utils.StringTool;
import com.biz.primus.common.utils.ValueUtils;
import com.biz.primus.ms.product.interfaces.ProductPriceGenerator;
import com.biz.primus.ms.product.interfaces.ProductPrototype;
import com.biz.primus.ms.product.service.ProductValidator;
import com.google.common.base.Function;
import com.google.common.collect.Lists;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;

import java.util.List;
import java.util.Optional;

/**
 * B类商品商品数据原型
 *
 * @author david-liu
 * @date 2017年01月17日
 * @reviewer
 * @see
 */
@Data
@Slf4j
@NoArgsConstructor
public class TypeBProductPrototype implements ProductPrototype {
    private static final long serialVersionUID = -40107377464669629L;


    private ProductPriceVo productPriceVo;

    /**
     * 商品门店价格生成器
     */
    private ProductPriceGenerator depotProductPriceGenerator;

    /**
     * 商品省仓门店价格生成器
     */
    private ProductPriceGenerator warehouseDepotProductPriceGenerator;

    /**
     * 商品Ro
     */
    private CommodityVo commodityVo;

    /**
     * 价格 Ro
     */
    private PriceVo depotPriceVo;

    /**
     * 省仓门店价格 Ro
     */
    private PriceVo warehouseDepotPriceRo;

    /**
     * 商品验证器
     */
    private ProductValidator validator;

    /**
     * 当前定位和就近门店的距离
     */
    private Integer distance;

    /**
     * 是否开启快喝模式
     */
    private Boolean isOpenKuaiheMode;

    /**
     * 门店商品Ro
     */
    private DepotCommodityVo depotProductVo;

    private ProductStockVo productStockVo;

    /**
     * 促销简单特价
     */
    private ProductSpecialOfferPromotionRespVo productSpecialOfferPromotion;

    /**
     * 商品详情促销信息
     */
    private List<PromotionBasicInfoVo> promotionBasicInfoVos;

    /**
     * 列表页商品促销标签
     */
    private ProductPromotionTagRespVo productPromotionTagRespVo;

    /**
     * 详情页通用构造器
     *
     * @param commodityVo
     * @param priceVo
     * @param stockVo
     * @param productSpecialOfferPromotion
     * @param promotionBasicInfoVo
     * @param productPromotionTagRespVo
     */
    public TypeBProductPrototype(CommodityVo commodityVo, ProductPriceVo priceVo, ProductStockVo stockVo,
                                 ProductSpecialOfferPromotionRespVo productSpecialOfferPromotion, List<PromotionBasicInfoVo> promotionBasicInfoVo,
                                 ProductPromotionTagRespVo productPromotionTagRespVo, Integer distance) {
        this.commodityVo = commodityVo;
        this.productPriceVo = priceVo;
        this.productStockVo = stockVo;
        this.productSpecialOfferPromotion = productSpecialOfferPromotion;
        this.promotionBasicInfoVos = promotionBasicInfoVo;
        this.productPromotionTagRespVo = productPromotionTagRespVo;
        this.distance = distance;
    }

    /**
     * 列表页通用构造器
     *
     * @param commodityVo
     * @param productPriceVo
     * @param stockVo
     * @param productSpecialOfferPromotionRespVo
     * @param productPromotionTagRespVo
     * @param distance                           配送距离计算
     */
    public TypeBProductPrototype(CommodityVo commodityVo, ProductPriceVo productPriceVo, ProductStockVo stockVo,
                                 ProductSpecialOfferPromotionRespVo productSpecialOfferPromotionRespVo,
                                 ProductPromotionTagRespVo productPromotionTagRespVo, Integer distance) {
        this.commodityVo = commodityVo;
        this.productPriceVo = productPriceVo;
        this.productStockVo = stockVo;
        this.productSpecialOfferPromotion = productSpecialOfferPromotionRespVo;
        this.productPromotionTagRespVo = productPromotionTagRespVo;
        this.distance = distance;
    }

    /**
     * 获取门店库存
     */
    @Override
    public Integer getDepotStock() {
        ProductStockVo productStockVo = this.getProductStockVo();
        //设置库存
        if (productStockVo == null || productStockVo.getStockRespVo() == null) {
            return 0;
        } else {
            return ValueUtils.getValue(productStockVo.getStockRespVo().getQuantity());
        }
    }

    /**
     * 获取区域库存
     */
    @Override
    public Integer getStock() {
        ProductStockVo productStockVo = this.getProductStockVo();
        //设置库存
        if (productStockVo == null || productStockVo.getStockRespVo() == null) {
            return 0;
        } else {
            return ValueUtils.getValue(productStockVo.getStockRespVo().getWarehouseQuantity());
        }
    }


    @Override
    public ProductCustomModelVo getProductCustomModelVo() {
        ProductCustomModelVo productCustomModelVo = new ProductCustomModelVo();
        //todo:add
        return null;
    }

    @Override
    public Long getProductId() {
        return this.commodityVo.getProductId();
    }

    @Override
    public Long getVendorId() {
        return this.commodityVo.getVendorId();
    }

    @Override
    public String getProductName() {
        return this.commodityVo.getName();
    }

    @Override
    public Integer getProductType() {
        return this.commodityVo.getProductType();
    }

    @Override
    public String getLogo() {
        return this.commodityVo.getLogo();
    }

    /**
     * 考虑库存 简单特价 获取价格信息
     *
     * @return
     */
    @Override
    public ProductFinalPriceVo getProductFinalPriceVo() {
        ProductFinalPriceVo respVo = new ProductFinalPriceVo();
        if (!this.depotStockFilter()) {
            //门店有库存
            if (!this.depotPriceFilter()) {
                //门店价格合法,设置门店价格
                respVo.setFinalPrice(this.getDepotFinalPrice());
                respVo.setFclSinglePrice(this.getPrice(ProductPriceVo::getDepotPrice, PriceVo::getFclSinglePrice));
                respVo.setEWalletPrice(this.getPrice(ProductPriceVo::getDepotPrice, PriceVo::getEwalletPrice));
                respVo.setFinalMarketPrice(this.getPrice(ProductPriceVo::getDepotPrice, PriceVo::getNormalPrice));
            } else if (!this.globalPriceFilter()) {
                //门店价格不合法,省仓价格合法
                respVo.setFinalPrice(this.getPrice(ProductPriceVo::getVirtualPrice, PriceVo::getFinalPrice));
                respVo.setFclSinglePrice(this.getPrice(ProductPriceVo::getVirtualPrice, PriceVo::getFclSinglePrice));
                respVo.setEWalletPrice(this.getPrice(ProductPriceVo::getVirtualPrice, PriceVo::getEwalletPrice));
                respVo.setFinalMarketPrice(this.getPrice(ProductPriceVo::getVirtualPrice, PriceVo::getNormalPrice));
            } else {
                return null;
            }
        } else if (!this.globalStockFilter()) {
            //区域有库存,门店无库存
            if (!this.globalPriceFilter()) {
                //区域价格合法
                respVo.setFinalPrice(this.getPrice(ProductPriceVo::getVirtualPrice, PriceVo::getFinalPrice));
                respVo.setFclSinglePrice(this.getPrice(ProductPriceVo::getVirtualPrice, PriceVo::getFclSinglePrice));
                respVo.setEWalletPrice(this.getPrice(ProductPriceVo::getVirtualPrice, PriceVo::getEwalletPrice));
                respVo.setFinalMarketPrice(this.getPrice(ProductPriceVo::getVirtualPrice, PriceVo::getNormalPrice));
            } else {
                //区域价格不合法
                return null;
            }
        } else {
            //门店区域都没有库存
            return null;
        }
        return respVo;
    }

    /**
     * 区域库存过滤器
     *
     * @return 区域没库存返回 true
     */
    private Boolean globalStockFilter() {
        if (this.productStockVo != null && this.productStockVo.getStockRespVo() != null
                && ValueUtils.getValue(this.productStockVo.getStockRespVo().getWarehouseQuantity()) > 0) {
            return Boolean.FALSE;
        }
        return Boolean.TRUE;
    }

    /**
     * 全国价格不合法 在相应场景 需要过滤掉
     *
     * @return 价格不合法返回 true
     */
    private boolean globalPriceFilter() {
        if (this.productPriceVo != null && this.productPriceVo.getVirtualPrice() != null
                && ValueUtils.getValue(this.productPriceVo.getVirtualPrice().getFinalPrice()) > Constant.MIN_SALE_PRICE) {
            return Boolean.FALSE;
        }
        return Boolean.TRUE;
    }

    /**
     * 获取价格 不存在时为null
     */
    private Integer getPrice(Function<ProductPriceVo, PriceVo> pp, Function<PriceVo, Integer> pi) {
        if (this.productPriceVo == null) {
            return null;
        }
        if (pp.apply(this.productPriceVo) == null) {
            return null;
        }
        Integer resp = pi.apply(pp.apply(this.productPriceVo));
        if (ValueUtils.getValue(resp) > Constant.MIN_SALE_PRICE) {
            return resp;
        } else {
            return null;
        }
    }

    /**
     * 门店价格过滤
     * @return 门店价格不合法返回true
     */
    private boolean depotPriceFilter() {
        if (this.productPriceVo != null && this.productPriceVo.getDepotPrice() != null
                && ValueUtils.getValue(this.productPriceVo.getDepotPrice().getFinalPrice()) > Constant.MIN_SALE_PRICE) {
            return Boolean.FALSE;
        }
        return Boolean.TRUE;
    }

    /**
     * 门店库存过滤
     * @return 门店无库存返回 true
     */
    private boolean depotStockFilter() {
        if (this.productStockVo != null && this.productStockVo.getStockRespVo() != null
                && ValueUtils.getValue(this.productStockVo.getStockRespVo().getQuantity()) > 0) {
            return Boolean.FALSE;
        }
        return Boolean.TRUE;
    }

    /**
     * 简单特价
     * @return 不合法返回0
     */
    private Integer getDepotSpecialOfferPromotion() {
        return Optional.ofNullable(this.productSpecialOfferPromotion)
                .filter(p->ValueUtils.getValue(p.getSpecialOfferPrice()) > Constant.MIN_SALE_PRICE)
                .map(ProductSpecialOfferPromotionRespVo::getSpecialOfferPrice).orElse(0);
    }

    @Override
    public Integer getSaleStatus() {
        return this.commodityVo.getSaleStatus();
    }

    @Override
    public List<String> getApartTags() {
        return Lists.newArrayList();
    }

    @Override
    public String getCategoryName() {
        return Optional.ofNullable(this.commodityVo.getCategoryName()).orElse("");
    }

    @Override
    public String getBrandName() {
        return Optional.ofNullable(this.commodityVo.getBrandName()).orElse("");
    }

    @Override
    public List<String> getIntroImages() {
        String introImages = Optional.ofNullable(commodityVo.getIntroImages()).orElse("");
        return Optional.ofNullable(StringTool.split(introImages, ",")).orElse(Lists.<String>newArrayList());
    }

    @Override
    public Boolean validate(Integer userLevel, Boolean validateStock) {
        return this.validator.doValidate(this, userLevel, validateStock);
    }

    @Override
    public void validateWithException(Integer userLevel, Boolean validateStock) {
        this.validator.doValidateWithException(this, userLevel, validateStock);
    }

    @Override
    public CommodityVo getCommodityVo() {
        return this.commodityVo;
    }

    @Override
    public ProductBaseVo getProductBaseVo() {
        ProductBaseVo productBaseVo = new ProductBaseVo();
        CopyUtils.copyProperties(this.commodityVo, productBaseVo);
        return productBaseVo;
    }

    @Override
    public String getProductCode() {
        return this.commodityVo.getProductCode();
    }

    @Override
    public String getVendorProductCode() {
        return this.commodityVo.getVendorProductCode();
    }

    @Override
    public String getSubTitle() {
        return this.commodityVo.getSubTitle();
    }

    @Override
    public Long vendorId() {
        return this.commodityVo.getVendorId();
    }

    @Override
    public Long getBrandId() {
        return this.commodityVo.getBrandId();
    }

    @Override
    public Long getCategoryId() {
        return this.commodityVo.getCategoryId();
    }

    @Override
    public List<String> getProductImages() {
        if (StringUtils.isNotBlank(this.commodityVo.getImages())) {
            return StringTool.split(this.commodityVo.getImages(), ",");
        } else {
            return Lists.newArrayList();
        }
    }

    @Override
    public Integer getWeight() {
        return this.commodityVo.getWeight();
    }

    @Override
    public Boolean getOpenKuaiheMode() {
        return isOpenKuaiheMode;
    }

    @Override
    public DeliverType getDeliverType() {
        if (ValueUtils.getValue(this.getDepotStock()) > 0) {
            return DeliverType.DEPOT_DELIVER;
        } else {
            return DeliverType.WAREHOUSE_DELIVER;
        }
    }

    private Integer getDepotFinalPrice() {
        if (this.getProductPriceVo() == null || this.getProductPriceVo().getDepotPrice() == null) {
            return 0;
        } else {
            if (this.getDepotSpecialOfferPromotion()<Constant.MIN_SALE_PRICE) {
                return ValueUtils.getValue(this.getProductPriceVo().getDepotPrice().getFinalPrice());
            } else {
                return ValueUtils.getValue(Math.min(ValueUtils.getValue(this.getDepotSpecialOfferPromotion())
                        , ValueUtils.getValue(this.getProductPriceVo().getDepotPrice().getFinalPrice())));
            }
        }
    }

    private Integer getVirtualFinalPrice() {
        if (this.getProductPriceVo() == null || this.getProductPriceVo().getVirtualPrice() == null ||
                ValueUtils.getValue(this.getProductPriceVo().getVirtualPrice().getFinalPrice()) < Constant.MIN_SALE_PRICE) {
            return 0;
        } else {
            return ValueUtils.getValue(this.getProductPriceVo().getVirtualPrice().getFinalPrice());
        }
    }

    @Override
    public ProductIdxVo toProductIdx(String depotCode) {
        ProductIdxVo vo = new ProductIdxVo();
        //设置库存
        vo.setDepotStock(this.getDepotStock());
        vo.setStock(this.getStock());
        if (vo.getDepotStock() <= 0 && vo.getStock() <= 0) {
            log.debug("toProductIdx 商品:{} 门店:{} 全省库存为0 跳过", this.getProductCode(), depotCode);
//            todo:调试过程中 不屏蔽库存进入索引
//            return null;

        }
        //设置价格
        if (vo.getDepotStock() > 0) {
            //设置门店价格
            vo.setPrice(this.getDepotFinalPrice());
            if (ValueUtils.getValue(vo.getPrice()) <= Constant.MIN_SALE_PRICE) {
                log.debug("toProductIdx 商品:{} 门店:{} 门店价格异常:{} 跳过", this.getProductCode(), depotCode, ValueUtils.getValue(vo.getPrice()));
                return null;
            }
        } else {
            //设置全国价格
            vo.setPrice(this.getVirtualFinalPrice());
            if (ValueUtils.getValue(vo.getPrice()) <= Constant.MIN_SALE_PRICE) {
                log.debug("toProductIdx 商品:{} 门店:{} 虚拟门店价格异常:{} 跳过", this.getProductCode(), depotCode, ValueUtils.getValue(vo.getPrice()));
                return null;
            }
        }
        vo.setId(String.format("%s%s%s", this.getVendorId(), depotCode, this.getProductCode()));
        vo.setProductId(String.valueOf(this.getProductId()));
        vo.setVendorId(this.getVendorId());
        vo.setName(this.getProductName());
        vo.setProductCode(this.getProductCode());
        vo.setSalesVolume(this.commodityVo.getSalesVolume());
        vo.setViewVolume(this.commodityVo.getViewVolume());
        vo.setCategory(this.commodityVo.getCategoryId());
        vo.setBrand(this.commodityVo.getBrandId());
        vo.setSaleTagIds(this.commodityVo.getSaleTagIds());
        vo.setOnSaleTime(this.commodityVo.getOnSaleTime());
        vo.setDepotCode(depotCode);
        vo.setSaleStatus(this.getSaleStatus());
        vo.setProductType(VendorType.TYPE_B.getValue());
        vo.setAppSaleStatus(this.commodityVo.getAppSaleStatus());
        vo.setWebSaleStatus(this.commodityVo.getWebSaleStatus());
        vo.setSeoDescription(this.commodityVo.getSeoDescription());
        vo.setSeoKeywords(this.commodityVo.getSeoKeywords());
        vo.setSeoTitle(this.commodityVo.getSeoTitle());
        vo.setExtendProductVoList(this.commodityVo.getExtendProducts());
        vo.setGlobalIdx(this.commodityVo.getGlobalIdx());
        return vo;
    }


    @Override
    public Integer getPredictTime() {
        if (ValueUtils.getValue(this.getDepotStock()) > 0 &&
                ValueUtils.getValue(this.distance) >= 0) {
            if (PeriodsOfDeliveriesTime.now.supported(this.distance)) {
                return PeriodsOfDeliveriesTime.now.getMinutes();
            } else if (PeriodsOfDeliveriesTime.half_hour.supported(this.distance)) {
                return PeriodsOfDeliveriesTime.half_hour.getMinutes();
            } else if (PeriodsOfDeliveriesTime.one_hour.supported(this.distance)) {
                return PeriodsOfDeliveriesTime.one_hour.getMinutes();
            } else {
                return PeriodsOfDeliveriesTime.today.getMinutes();
            }
        } else {
            return PeriodsOfDeliveriesTime.today.getMinutes();
        }
    }

    @Override
    public List<String> getSaletagIds() {
        return this.commodityVo.getSaleTagIdsList();
    }

    @Override
    public Integer getSalesVolume() {
        return Optional.ofNullable(this.getCommodityVo().getSalesVolume()).orElse(0);
    }


    @Override
    public void clearWarehouseStock() {
        this.getProductStockVo().getStockRespVo().setQuantity(0);
        this.getProductStockVo().getStockRespVo().setQuantity(0);
    }

    @Override
    public List<ExtendProductVo> getExtends() {
        return this.commodityVo.getExtendProducts();
    }

    @Override
    public Boolean inSaleArea(String targetSaleArea) {
        return Boolean.TRUE;
    }

    @Override
    public List<PromotionBasicInfoVo> getPromotionBasicInfoVos() {
        return this.promotionBasicInfoVos;
    }

}
